package controllers;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

import models.Course;
import models.Student;
import models.Teacher;
import models.TeachingSession;
import data.CourseDAO;
import data.ICourseDAO;
import spark.Request;
import spark.Response;

public class CourseController extends BaseController {
	private ICourseDAO dao;
	
	public CourseController(Request request, Response response) {
		super(request, response);
		dao = new CourseDAO();
	}
	
	public Object list() {
		Map<String, Object> attributes = new HashMap<>();
		try{
			List<Course> courses;
			if(this.isUserInRole("Admin")){
				courses = dao.list();
			} else if(this.isUserInRole("Tutor") || this.isUserInRole("Lecturer")){
				courses = dao.listTeacherCourses(this.getCredentials().getPersonId());
			} else {
				courses = dao.listStudentCourses(this.getCredentials().getPersonId());
			}
			
			attributes.put("courses", courses);
		}catch(Exception e) {
			attributes.put("error", e.getMessage());
			return render(attributes, "error.html");
		}
		return render(attributes, "course/list.html");
	}
	
	public Object getLecturers(){
		Map<String, Object> attributes = new HashMap<>();
		try {
			ObjectMapper mapper = new ObjectMapper();
			
			
			int courseId = Integer.parseInt( request.params(":id"));
			List<Teacher> tutors = dao.listLecturers(courseId);
			return mapper.writeValueAsString(tutors);
		} catch (JsonGenerationException e) {
			attributes.put("error", e.getMessage());
			return render(attributes, "error.html");
		} catch (JsonMappingException e) {
			attributes.put("error", e.getMessage());
			return render(attributes, "error.html");
		} catch (IOException e) {
			attributes.put("error", e.getMessage());
			return render(attributes, "error.html");
		}
		
	}
	
	public Object getTutors(){
		Map<String, Object> attributes = new HashMap<>();
		
		try {
			
			ObjectMapper mapper = new ObjectMapper();
			
			
			int courseId = Integer.parseInt( request.params(":id"));
			List<Teacher> tutors = dao.listTutors(courseId);
			return mapper.writeValueAsString(tutors);
		} catch (JsonGenerationException e) {
	
			attributes.put("error", e.getMessage());
			return render(attributes, "error.html");
		} catch (JsonMappingException e) {
			attributes.put("error", e.getMessage());
			return render(attributes, "error.html");
		} catch (IOException e) {
			attributes.put("error", e.getMessage());
			return render(attributes, "error.html");
		}
		
	}
	
	public Object get(){
		int id = Integer.parseInt( request.params(":id"));

		Course course = dao.get(id);
		Map<String, Object> attributes = new HashMap<>();
		attributes.put("course", course);
		
		return render(attributes, "course/view.html");
	}
	
	public Object listSessions(){
		Map<String, Object> attributes = new HashMap<>();
		try{
			int courseId = Integer.parseInt( request.params(":id"));
			List<TeachingSession> sessions = dao.listSessions(courseId);
			
			attributes.put("sessions", sessions);
			attributes.put("courseId", courseId);
		}catch(Exception e) {
			attributes.put("error", e.getMessage());
			return render(attributes, "error.html");
		}
		return render(attributes, "course/list_sessions.html");
	}
	
	public Object listTeachers(){
		Map<String, Object> attributes = new HashMap<>();
		try{
			int courseId = Integer.parseInt( request.params(":id"));
			List<Teacher> teachers = dao.listTeachers(courseId);
			attributes.put("teachers", teachers);
			attributes.put("courseId", courseId);
		}catch(Exception e) {
			attributes.put("error", e.getMessage());
			return render(attributes, "error.html");
		}
		return render(attributes, "course/list_teachers.html");
	}
	
	public Object listStudents(){
		Map<String, Object> attributes = new HashMap<>();
		try{
			int courseId = Integer.parseInt( request.params(":id"));
			List<Student> students = dao.listStudents(courseId);
			attributes.put("courseId", courseId);
			attributes.put("students", students);
		}catch(Exception e) {
			attributes.put("error", e.getMessage());
			return render(attributes, "error.html");
		}
		return render(attributes, "course/list_students.html");
	}
	
	public Object manageStudentsByTutor(){
		Map<String, Object> attributes = new HashMap<>();
		if(request.requestMethod().toUpperCase().equals("GET")){
			int courseId = Integer.parseInt( request.params(":id"));
			int tutorId = Integer.parseInt( request.params(":tutorId"));
			String tutorName = "";
			try {
				tutorName = URLDecoder.decode(request.params(":tutorName"), "UTF-8");
			} catch (UnsupportedEncodingException e) {
	
				e.printStackTrace();
			}
			
			List<Student> unassignedStudents = dao.getUnassignedStudents(courseId);
			List<Student> assignedStudents = dao.getTutorStudents(courseId, tutorId);
			attributes.put("assignedStudents", assignedStudents);
			attributes.put("unassignedStudents", unassignedStudents);
			attributes.put("courseId", courseId);
			attributes.put("tutorId", tutorId);
			attributes.put("tutorName", tutorName);
			
			return render(attributes, "course/manage_students_tutor.html");
		}else {
			int courseId = Integer.parseInt( request.queryParams("courseId"));
			int tutorId = Integer.parseInt( request.queryParams("tutorId"));
			//String tutorName = request.queryParams("tutorName");
			String[] studentIds = request.raw().getParameterValues("students");
			
			dao.addStudentsToTutor(courseId, tutorId, studentIds);
			
			response.status(201);
			redirect(this.getCurrentRequestUrl());
			return "";
		}
	}
	
	public Object addTeachingSession(){
		Map<String, Object> attributes = new HashMap<>();
		if(request.requestMethod().toUpperCase().equals("GET")){
			
			int courseId = Integer.parseInt( request.params(":id"));
			TeachingSession session = new TeachingSession();
			
			Course course = new Course();
			course.setId(courseId);
			session.setCourse(course);
			
			attributes.put("session", session);
			attributes.put("teachers", dao.listTeachers(courseId));
			attributes.put("rooms", dao.getRooms());
			return render(attributes, "course/add_session.html");
		} else {
			
			int courseId = Integer.parseInt( request.queryParams("courseId"));
			int sessionType = Integer.parseInt( request.queryParams("sessionType"));
			int roomId = Integer.parseInt( request.queryParams("roomId"));
			int teacherId = Integer.parseInt( request.queryParams("teacherId"));
			String name = request.queryParams("name");
			
			String dateInString = request.queryParams("date");
			SimpleDateFormat formatter = new SimpleDateFormat("MM-dd-yyyy HH:mm");
			Date date;
			try {
				date = formatter.parse(dateInString);
			} catch (ParseException e) {
				attributes.put("error", e.toString());
				redirect(this.getCurrentRequestUrl());
				return "";
			}

			
			dao.insertTeachingSession(courseId, sessionType, teacherId, roomId, date, name);
			response.status(201);
			redirect("courses/" + courseId);
			return "";
		
		}
	}

}
